//! Copyright 2012 NTH Technology, Inc.
//! All rights reserved
//!
#ifndef __FIFO_h__
#define __FIFO_h__

#include "BasicTypes.h"

//! Basic U32 FIFO
//! This FIFO is not thread safe
//!
class cFIFO
{
public:
    //! Initializes the FIFO
    //!
    //! \param pStorage     [in]    Storage space
    //! \param Size         [in]    Number of elements
    inline void Init( U32* pStorage, U32 Size )
    {
        m_pStorage = pStorage;
        m_Size     = Size;
        m_Count    = 0;
        m_Head     = 0;
        m_Tail     = 0;
    }

public:
    //! Pushes an element
    //!
    //! \param Element  [in]
    //!
    //! \return bool
    //!                 true    operation succeeded
    //!                 false   operation failed (FIFO full)
    inline bool Push( U32 Element )
    {
        if ( m_Count == m_Size ) { return( false ); }

        m_pStorage[ m_Tail++ ] = Element;
        if ( m_Tail == m_Size ) { m_Tail = 0; }
        ++m_Count;

        return( true );
    }

    //! Pops and element
    //!
    //! \param Element  [out]
    //!
    //! \return bool
    //!                 true    operation succeeded
    //!                 false   operation failed (FIFO empty)
    inline bool Pop( U32& Element )
    {
        if ( 0 == m_Count ) { return( false ); }

        Element = m_pStorage[ m_Head++ ];
        if ( m_Head == m_Size ) { m_Head = 0; }
        --m_Count;

        return( true );
    }

    //! Removes the head element
    //!
    //!
    //! \return bool
    //!                 true    operation succeeded
    //!                 false   operation failed (FIFO empty)
    inline bool Pop()
    {
        if ( 0 == m_Count ) { return( false ); }

        ++m_Head;
        if ( m_Head == m_Size ) { m_Head = 0; }
        --m_Count;

        return( true );
    }

    //! Peeks the head
    //!
    //! \param Element  [out]
    //!
    //! \return bool
    //!                 true    operation succeeded
    //!                 false   operation failed (FIFO empty)
    inline bool Peek( U32& Element )
    {
        if ( 0 == m_Count ) { return( false ); }

        Element = m_pStorage[ m_Head ];

        return( true );
    }

    //! Retrieves the element count
    //!
    //!
    //! \return U32
    inline U32 Count()
    {
        return( m_Count );
    }

public:
    //! Retrieves the size
    //!
    //!
    //! \return U32
    inline U32 Size()
    {
        return( m_Size );
    }

private:
    U32* m_pStorage;
    U32  m_Count;
    U32  m_Head;
    U32  m_Tail;
    U32  m_Size;
};

#endif // __FIFO_h__
